// Compiler.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Basic.h"
#include "Lexer.h"
#include "Parser.h"
#include "SyntaxVisitors.h"
#include "LibIO.h"
#include "CodeGenerator.h"
#include "Machine.h"

using namespace CoreLib::Basic;
using namespace SimpleC::Compiler;
using namespace CoreLib::IO;
using namespace SimpleC;

void PrintError(List<CompileError> &errorList)
{
	if (errorList.Count() > 0)
	{
		for (int i = 0; i<errorList.Count(); i++)
		{
			printf("%s line %d, col %d\n", errorList[i].Message.ToMultiByteString(), errorList[i].Line, errorList[i].Col);
		}
	}
}
int wmain(int argc, wchar_t* argv[])
{
	if (argc >= 2)
	{
		List<CompileError> errorList;
		RefPtr<ProgramSyntaxNode> programSyntaxNode = new ProgramSyntaxNode();
		for (int i = 1; i < argc; i++)
		{
			StreamReader reader(new FileStream(argv[i], FileMode::Open), Encoding::Ansi);
			String source = reader.ReadToEnd();
			Lexer lexer;
			auto tokens = lexer.Parse(argv[i], source, errorList);
			Parser parser(tokens, errorList, L"testet");
			programSyntaxNode->CombineWith(*parser.Parse());
		}
		if (errorList.Count() > 0)
		{
			PrintError(errorList);
			return 0;
		}
		RefPtr<SyntaxVisitor> visitor = CreateSemanticsVisitor(errorList);
		programSyntaxNode->Accept(visitor.Ptr());
		if (errorList.Count() > 0)
		{
			PrintError(errorList);
			return 0;
		}
		CodeGenerator codeGen;
		programSyntaxNode->Accept(&codeGen);
		codeGen.ProgramBinaryCode->Dump(Path::ReplaceExt(argv[1], L"code.txt"));
		Machine machine;
		try
		{
			machine.Run(codeGen.ProgramBinaryCode.Ptr());
			//machine.PrintStack();
		}
		catch (RuntimeException e)
		{
			wprintf_s(L"%s\n", e.Message.Buffer());
		}
		PrintError(errorList);
	}
	return 0;
}

